home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / AX25CMD.C < prev    next >
C/C++ Source or Header  |  1997-09-14  |  43KB  |  1,791 lines

  1. /* AX25 control commands
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by G1EMM
  5.  * Mods by PA0GRI
  6.  * Mods by N1BEE
  7.  */
  8. /*
  9. ** FILE: ax25cmd.c
  10. **
  11. ** AX.25 command handler.
  12. **
  13. ** 09/24/90 Bob Applegate, wa2zzx
  14. **    Added BCTEXT, BC, and BCINTERVAL commands for broadcasting an id
  15. **    string using UI frames.
  16. **
  17. ** 27/09/91 Mike Bilow, N1BEE
  18. **    Added Filter command for axheard control
  19. */
  20.  
  21. #include "global.h"
  22. #ifdef AX25
  23. #include "commands.h"
  24. #include "mbuf.h"
  25. #include "timer.h"
  26. #include "proc.h"
  27. #include "iface.h"
  28. #include "mailbox.h"
  29. #ifndef MSDOS
  30. #include "session.h"
  31. #endif
  32. #include "nr4.h"
  33. #include "pktdrvr.h"
  34. #include "netrom.h"
  35. #include "pool.h"
  36.  
  37. #if !defined(_lint)
  38. static char rcsid[] OPTIONAL = "$Id: ax25cmd.c,v 1.28 1997/09/14 14:37:46 root Exp root $";
  39. #endif
  40.  
  41. static int doaxdest (int argc,char *argv[],void *p);
  42. static int doaxfilter (int argc, char *argv[], void *p);
  43. static int doaxflush (int argc, char *argv[], void *p);
  44. static int doaxirtt (int argc, char *argv[], void *p);
  45. static int doaxkick (int argc, char *argv[], void *p);
  46. static int doaxreset (int argc, char *argv[], void *p);
  47. static int doaxroute (int argc, char *argv[], void *p);
  48. static int doaxwindow (int argc, char *argv[], void *p);
  49. static int dobc (int argc, char *argv[], void *p);
  50. static int dobcint (int argc, char *argv[], void *p);
  51. static int dobcport (int argc, char *argv[], void *p);
  52. static int dobctext (int argc, char *argv[], void *p);
  53. static int doaxhport (int argc, char *argv[], void *p);
  54. static int doaxhsize (int argc, char *argv[], void *p);
  55. static int doblimit (int argc, char *argv[], void *p);
  56. static int doaxuser (int argc, char *argv[], void *p);
  57. static int dodigipeat (int argc, char *argv[], void *p);
  58. static int domaxframe (int argc, char *argv[], void *p);
  59. static int domycall (int argc, char *argv[], void *p);
  60. static int don2 (int argc, char *argv[], void *p);
  61. static int dopaclen (int argc, char *argv[], void *p);
  62. static int dopthresh (int argc, char *argv[], void *p);
  63. static int dot3 (int argc, char *argv[], void *p);
  64. static int doaxtype (int argc, char *argv[], void *p);
  65. static int dot4 (int argc, char *argv[], void *p);
  66. static int doaxversion (int argc, char *argv[], void *p);
  67. static int doaxmaxwait (int argc, char *argv[], void *p);
  68. static int dosmartroute (int argc, char *argv[], void *p);
  69. static int axdest (struct iface * ifp);
  70. static int dorosecall (int argc, char *argv[], void *p);
  71. static int docall (int argc, char *argv[], void *p, char call[]);
  72. static int doax25paclen (int argc, char *argv[], void *p);
  73. static int doax25timertype (int argc, char *argv[], void *p);
  74. static int doax25irtt (int argc, char *argv[], void *p);
  75. static int doax25version (int argc, char *argv[], void *p);
  76. static int doax25t3 (int argc, char *argv[], void *p);
  77. static int doax25t4 (int argc, char *argv[], void *p);
  78. static int doax25n2 (int argc, char *argv[], void *p);
  79. static int doax25maxframe (int argc, char *argv[], void *p);
  80. static int doax25pthresh (int argc, char *argv[], void *p);
  81. static int doax25window (int argc, char *argv[], void *p);
  82. static int doax25blimit (int argc, char *argv[], void *p);
  83. static int doax25maxwait (int argc, char *argv[], void *p);
  84. static void dobroadtick (void);
  85. static void displaycounters (struct iface *ifp, int addseparator);
  86.  
  87. #ifdef TUTOR
  88. static int dotutorcall (int argc, char *argv[], void *p);
  89. static int doinfocall (int argc, char *argv[], void *p);
  90. static int donewscall (int argc, char *argv[], void *p);
  91. #endif
  92.  
  93. #ifdef AXBCSTR
  94. static void ax_bc (struct iface * axif, char *str);
  95. #else
  96. static void ax_bc (struct iface * axif);
  97. #endif
  98.  
  99. #ifdef TTYCALL
  100. static int dottycall (int argc, char *argv[], void *p);
  101. extern char Ttycall[AXALEN];    /* the ttylink call in 'call' form */
  102. #endif
  103.  
  104. extern int axheard_filter_flag;    /* in axheard.c */
  105. extern int lapbtimertype;
  106. extern char Tcall[AXALEN];
  107. extern char Icall[AXALEN];
  108. extern char Ncall[AXALEN];
  109. extern char Myalias[AXALEN];
  110. extern char Nralias[ALEN + 1];
  111.  
  112.  
  113. /* Defaults for IDing. */
  114. static char *axbctext = NULLCHAR;        /* Text to send */
  115. static struct timer Broadtimer;    /* timer for broadcasts */
  116. char AXRosecall[AXALEN];
  117. int AXSmartRoute = 0;
  118. static long Axmaxwait = 0;
  119. int Maxax25heard;
  120.  
  121.  
  122. #ifdef POOLED
  123. extern struct mempool lq_pool;
  124. extern struct mempool ld_pool;
  125. #endif
  126.  
  127.  
  128. #ifdef CATALOG
  129. #include "catalog.h"
  130.  
  131. #define CAT ax25cmd_catalog
  132.  
  133. #define smartroute    __STR(0)
  134. #define badalias    __STR(1)
  135. #define noiface        __STR(2)
  136. #define notax25        __STR(3)
  137. #define bcaststr    __STR(4)
  138. #define bcasttimer    __STR(5)
  139. #define maxheard    __STR(6)
  140. #define alsonotax25    __STR(7)
  141. #define notactive    __STR(8)
  142. #define heardheader    __STR(9)
  143. #define heardheader2    __STR(10)
  144. #define destheader    __STR(11)
  145. #define heardfilter    __STR(12)
  146. #define filterusage    __STR(13)
  147. #define filtersrc    __STR(14)
  148. #define filterdest    __STR(15)
  149. #define stopstr        __STR(16)
  150. #define lumsstr        __STR(17)
  151. #define srttmdev    __STR(18)
  152. #define T1_4str        __STR(19)
  153. #define blimitstr    __STR(20)
  154. #define maxwaitstr    __STR(21)
  155. #define axversionstr    __STR(22)
  156. #define irttstr        __STR(23)
  157. #define polltimerstr    __STR(24)
  158. #define redundancystr    __STR(25)
  159. #define retrylimitstr    __STR(26)
  160. #define maxframestr    __STR(27)
  161. #define paclenstr    __STR(28)
  162. #define pthreshstr    __STR(29)
  163. #define windowstr    __STR(30)
  164. #define badcallsign    __STR(31)
  165. #define toomany        __STR(32)
  166. #define baddigi        __STR(33)
  167. #define addfailed    __STR(34)
  168. #define routeheader    __STR(35)
  169. #define routeusage    __STR(36)
  170. #define badtarget    __STR(37)
  171. #define notintable    __STR(38)
  172. #define timertypestr    __STR(39)
  173. #define timertypeusage    __STR(40)
  174. #define bctext_str    __STR(41)
  175.  
  176. #else /* CATALOG */
  177.  
  178. static const char smartroute[] = "AX25 Smart Routing";
  179. static const char badalias[] = "can't set alias\n";
  180. static const char noiface[] = "you need to specify an interface\n";
  181. static const char notax25[] = "not an AX.25 interface\n";
  182. static const char bcaststr[] = "Broadcast text: %s\n";
  183. static const char bcasttimer[] = "Broadcast timer %lu/%lu seconds\n";
  184. static const char maxheard[] = "Max ax-heard";
  185. static const char alsonotax25[] = "Interface %s not AX.25 type interface\n";
  186. static const char notactive[] = "not active\n";
  187. static const char heardheader[] = "Interface  Station   Time since send  Pkts sent\n";
  188. static const char heardheader2[] = "Station   Time since heard Pkts rcvd : Station   Time since heard Pkts rcvd\n";
  189. static const char destheader[] = "Station   Last ref         Last heard           Pkts\n";
  190. static const char heardfilter[] = "ax25 heard filter";
  191. static const char filterusage[] = "Usage: ax25 filter <0|1|2|3>\n";
  192. static const char filtersrc[] = "Callsign logging by source %sabled, ";
  193. static const char filterdest[] = "by destination %sabled\n";
  194. static const char stopstr[] = "stop";
  195. static const char lumsstr[] = "/%lu ms; ";
  196. static const char srttmdev[] = "srtt = %lu mdev = %lu ";
  197. static const char T1_4str[] = "T%c: ";
  198. static const char blimitstr[] = "blimit";
  199. static const char maxwaitstr[] = "retry maxwait";
  200. static const char axversionstr[] = "AX25 version";
  201. static const char irttstr[] = "Initial RTT (ms)";
  202. static const char polltimerstr[] = "Idle poll timer (ms)";
  203. static const char redundancystr[] = "Link redundancy timer (sec)";
  204. static const char retrylimitstr[] = "Retry limit";
  205. static const char maxframestr[] = "Window size (frames)";
  206. static const char paclenstr[] = "Max frame length (bytes)";
  207. static const char pthreshstr[] = "Poll threshold (bytes)";
  208. static const char windowstr[] = "AX25 receive window (bytes)";
  209. static const char badcallsign[] = "Bad callsign %s\n";
  210. static const char toomany[] = "Too many digipeaters, or badly formed command.\n";
  211. static const char baddigi[] = "Bad digipeater %s\n";
  212. static const char addfailed[] = "Route add failed\n";
  213. static const char routeheader[] = "Target    Iface  Type  Mode Digipeaters\n";
  214. static const char routeusage[] = "Usage: ax25 route add <target> <iface> [digis...]\n       ax25 route drop <target> <iface>\n       ax25 route mode <target> <iface> [mode]\n";
  215. static const char badtarget[] = "Bad target %s\n";
  216. static const char notintable[] = "Not in table\n";
  217. static const char timertypestr[] = "AX25 timer type is ";
  218. static const char timertypeusage[] = "use: ax25 timertype [original|linear|exponential]\n";
  219. static const char bctext_str[] = "Bctext : %s\n";
  220.  
  221. #endif /* CATALOG */
  222.  
  223.  
  224. static const char lustr[] = "%lu";
  225. static const char unknownmode[] = "Unknown mode %s\n";
  226. static const char unknowncmd[] = "Unknown command %s\n";
  227. static const char originalstr[] = "original\n";
  228. static const char linearstr[] = "linear\n";
  229. static const char exponentialstr[] = "exponential\n";
  230. static const char strCR[] = "%s\n";
  231. static const char heardfmt[] = "%-9s  %-9s   %12s    %7lu\n";
  232. static const char str17[] = "%-17s";
  233.  
  234. static const char axstatheader[] =
  235. #if defined(UNIX) || defined(TNOS_68K)
  236.     "&AXB     Snd-Q   Rcv-Q   Remote    Local     Iface  State\n";
  237. #else
  238.     "&AXB Snd-Q   Rcv-Q   Remote    Local     Iface  State\n";
  239. #endif
  240.  
  241. static const char axstatfmt[] =
  242. #if defined(UNIX) || defined(TNOS_68K)
  243.     "%8.8lx %-8d%-8d%-10s%-10s%-7s%s\n";
  244. #else
  245.     "%4.4x %-8d%-8d%-10s%-10s%-7s%s\n";
  246. #endif
  247.  
  248. static const char axcbheader[] =
  249. #if defined(UNIX) || defined(TNOS_68K)
  250.     "&AXB     Local     Remote    Iface  RB V(S) V(R) Unack P Retry State\n";
  251. #else
  252.     "&AXB Local     Remote    Iface  RB V(S) V(R) Unack P Retry State\n";
  253. #endif
  254.  
  255. static const char axcbfmt[] =
  256. #if defined(UNIX) || defined(TNOS_68K)
  257.     "%8.8lx %-9s %-9s %-6s %c%c";
  258. #else
  259.     "%4.4x %-9s %-9s %-6s %c%c";
  260. #endif
  261.  
  262.  
  263.  
  264. const char *Ax25states[] =
  265. {
  266.     "",
  267.     "Disconnected",
  268.     "Listening",
  269.     "Conn pending",
  270.     "Disc pending",
  271.     "Connected",
  272.     "Recovery",
  273. };
  274.  
  275.  
  276. /* Ascii explanations for the disconnect reasons listed in lapb.h under
  277.  * "reason" in ax25_cb
  278.  */
  279. const char *Axreasons[] =
  280. {
  281.     "Normal",
  282.     "DM received",
  283.     "Timeout"
  284. };
  285.  
  286.  
  287.  
  288. static struct cmds Axcmds[] =
  289. {
  290.     { "alias",    donralias,    0, 0, NULLCHAR },
  291.     { "bc",        dobc,        0, 0, NULLCHAR },
  292.     { "bcinterval",    dobcint,    0, 0, NULLCHAR },
  293.     { "bcport",    dobcport,    0, 0, NULLCHAR },
  294.     { "blimit",    doblimit,    0, 0, NULLCHAR },
  295.     { "bctext",    dobctext,    0, 0, NULLCHAR },
  296.     { "counters",    doaxcounters,    0, 0, NULLCHAR },
  297.     { "dest",    doaxdest,    0, 0, NULLCHAR },
  298.     { "digipeat",    dodigipeat,    0, 0, NULLCHAR },
  299.     { "filter",    doaxfilter,    0, 0, NULLCHAR },
  300.     { "flush",    doaxflush,    0, 0, NULLCHAR },
  301.     { "heard",    doaxheard,    0, 0, NULLCHAR },
  302.     { "hearddest",    doaxdest,    0, 0, NULLCHAR },
  303.     { "hport",    doaxhport,    0, 0, NULLCHAR },
  304.     { "hsize",    doaxhsize,    0, 0, NULLCHAR },
  305. #ifdef TUTOR
  306.     { "infocall",    doinfocall,    0, 0, NULLCHAR },
  307. #endif
  308.     { "irtt",    doaxirtt,    0, 0, NULLCHAR },
  309.     { "kick",    doaxkick,    0, 2, "ax25 kick <axcb>" },
  310.     { "maxframe",    domaxframe,    0, 0, NULLCHAR },
  311.     { "maxwait",    doaxmaxwait,    0, 0, NULLCHAR },
  312.     { "mycall",    domycall,    0, 0, NULLCHAR },
  313. #ifdef TUTOR
  314.     { "newscall",    donewscall,    0, 0, NULLCHAR },
  315. #endif
  316.     { "paclen",    dopaclen,    0, 0, NULLCHAR },
  317.     { "pthresh",    dopthresh,    0, 0, NULLCHAR },
  318.     { "reset",    doaxreset,    0, 2, "ax25 reset <axcb>" },
  319.     { "retries",    don2,        0, 0, NULLCHAR },
  320.     { "rosecall",    dorosecall,    0, 0, NULLCHAR },
  321.     { "route",    doaxroute,    0, 0, NULLCHAR },
  322.     { "smartroute",    dosmartroute,    0, 0, NULLCHAR },
  323.     { "status",    doaxstat,    0, 0, NULLCHAR },
  324.     { "t3",        dot3,        0, 0, NULLCHAR },
  325.     { "t4",        dot4,        0, 0, NULLCHAR },
  326.     { "timertype",    doaxtype,    0, 0, NULLCHAR },
  327. #ifdef TUTOR
  328.     { "tutorcall",    dotutorcall,    0, 0, NULLCHAR },
  329. #endif
  330. #ifdef TTYCALL
  331.     { "ttycall",    dottycall,    0, 0, NULLCHAR },
  332. #endif
  333.     { "user",    doaxuser,    0, 0, NULLCHAR },
  334.     { "version",    doaxversion,    0, 0, NULLCHAR },
  335.     { "window",    doaxwindow,    0, 0, NULLCHAR },
  336.     { NULLCHAR,    NULL,        0, 0, NULLCHAR }
  337. };
  338.  
  339.  
  340.  
  341. /* Multiplexer for top-level ax25 command */
  342. int
  343. doax25 (int argc, char *argv[], void *p)
  344. {
  345.     return subcmd (Axcmds, argc, argv, p);
  346. }
  347.  
  348.  
  349.  
  350. int
  351. dosmartroute (int argc, char *argv[], void *p OPTIONAL)
  352. {
  353.     return setbool (&AXSmartRoute, smartroute, argc, argv);
  354. }
  355.  
  356.  
  357.  
  358. int
  359. donralias (int argc, char *argv[], void *p OPTIONAL)
  360. {
  361. char tmp[AXBUF];
  362.  
  363.     if (argc < 2) {
  364.         tprintf (strCR, pax25 (tmp, Myalias));
  365.         return 0;
  366.     }
  367.     if ((setcall (Myalias, argv[1]) == -1)
  368. #ifdef NETROM
  369.         || (putalias (Nralias, argv[1], 1) == -1)
  370. #endif
  371.         ) {
  372.         tputs (badalias);
  373.         Myalias[0] = '\0';
  374. #ifdef NETROM
  375.         Nralias[0] = '\0';
  376. #endif
  377.         return 0;
  378.     }
  379. #ifdef MAILBOX
  380.     setmbnrid ();
  381. #endif
  382.     return 0;
  383. }
  384.  
  385.  
  386.  
  387. /*
  388. ** This function is called to send the current broadcast message
  389. ** and reset the timer.
  390. */
  391.  
  392. static int 
  393. dobc (int argc, char *argv[], void *p OPTIONAL)
  394. {
  395. struct iface *ifa;
  396.  
  397.     if (argc < 2) {
  398.         tputs (noiface);
  399.         return 1;
  400.     }
  401.     if ((ifa = if_lookup (argv[1])) == NULLIF)
  402.         tprintf (Badinterface, argv[1]);
  403.     else if (ifa->type != CL_AX25)
  404.         tputs (notax25);
  405. #ifdef AXBCSTR
  406.     else if (argc > 2)
  407.         ax_bc (ifa, argv[2]);
  408. #endif
  409.     else {
  410. #ifdef AXBCSTR
  411.         ax_bc (ifa, ifa->ax25->bctext);
  412. #else
  413.         ax_bc (ifa);
  414. #endif
  415.         start_detached_timer (&Broadtimer);    /* stops if running and fire it up */
  416.     }
  417.     return 0;
  418. }
  419.  
  420.  
  421.  
  422. /*
  423. ** View/Change the message we broadcast.
  424. */
  425.  
  426. static int 
  427. dobctext (int argc, char *argv[], void *p OPTIONAL)
  428. {
  429. struct iface *ifp;
  430.  
  431.     if (argc < 2)
  432.         tprintf (bcaststr, axbctext);
  433.     else {
  434.         if (axbctext != NULL)
  435.             free (axbctext);
  436.         axbctext = strdup (argv[1]);
  437.         /* Set all ax.25 interfaces with no bc text */
  438.         for (ifp = Ifaces; ifp->next; ifp = ifp->next)
  439.             if (ifp->type == CL_AX25 && ifp->ax25->bctext == NULL)
  440.                 ifp->ax25->bctext = strdup (axbctext);
  441.     }
  442.     return 0;
  443. }
  444.  
  445.  
  446.  
  447. /*
  448. ** Examine/change the broadcast interval.
  449. */
  450.  
  451. static int 
  452. dobcint (int argc, char *argv[], void *p OPTIONAL)
  453. {
  454.     if (argc < 2) {
  455.         tprintf (bcasttimer,
  456.              read_timer (&Broadtimer) / 1000L,
  457.              dur_timer (&Broadtimer) / 1000L);
  458.         return 0;
  459.     }
  460.     stop_timer (&Broadtimer);    /* in case it's already running */
  461.     Broadtimer.func = (void (*)(void *)) dobroadtick;    /* what to call on timeout */
  462.     Broadtimer.arg = NULLCHAR;    /* dummy value */
  463.     set_timer (&Broadtimer, atoi (argv[1]) * 1000L);    /* set timer duration */
  464.     start_detached_timer (&Broadtimer);    /* and fire it up */
  465.     return 0;
  466. }
  467.  
  468.  
  469. /* Configure a port to do ax.25 beacon broadcasting */
  470. static int
  471. dobcport (int argc, char *argv[], void *p)
  472. {
  473.     return (dosetflag (argc, argv, p, AX25_BEACON, 1));
  474. }
  475.  
  476.  
  477.  
  478. /* Set the size of the ax.25 heard list */
  479. int 
  480. doaxhsize (int argc, char *argv[], void *p)
  481. {
  482.     if (argc > 1)        /* if setting new size ... */
  483.         (void) doaxflush (argc, argv, p);    /* we flush to avoid memory problems - K5JB */
  484.     return setint (&Maxax25heard, maxheard, argc, argv);
  485. }
  486.  
  487.  
  488.  
  489. /* Configure a port to do ax.25 heard logging */
  490. static int
  491. doaxhport (int argc, char *argv[], void *p)
  492. {
  493.     return (dosetflag (argc, argv, p, LOG_AXHEARD, 1));
  494. }
  495.  
  496.  
  497.  
  498. static void
  499. dobroadtick ()
  500. {
  501. struct iface *ifa;
  502.  
  503.     ifa = Ifaces;
  504.  
  505.     while (ifa != NULL) {
  506.         if (ifa->flags & AX25_BEACON)
  507. #ifdef AXBCSTR
  508.             ax_bc (ifa, ifa->ax25->bctext);
  509. #else
  510.             ax_bc (ifa);
  511. #endif
  512.         ifa = ifa->next;
  513.     }
  514.  
  515.     /* Restart timer */
  516.     start_detached_timer (&Broadtimer);
  517. }
  518.  
  519.  
  520.  
  521. /*
  522. ** This is the low-level broadcast function.
  523. */
  524.  
  525. #ifdef AXBCSTR
  526. static void 
  527. ax_bc (struct iface *axif, char *theaxbctext)
  528. #else
  529. static void 
  530. ax_bc (struct iface *axif)
  531. #endif
  532. {
  533. struct mbuf *hbp;
  534. int i;
  535. #ifndef AXBCSTR
  536. char *theaxbctext = axif->ax25->bctext;
  537. #endif
  538.  
  539.     /* prepare the header */
  540.     if ((theaxbctext == NULLCHAR) || (i = (int) strlen (theaxbctext)) == 0)
  541.         return;
  542.  
  543.     if ((hbp = alloc_mbuf ((int16) i)) == NULLBUF)
  544.         return;
  545.  
  546.     hbp->cnt = (int16) i;
  547.     memcpy (hbp->data, theaxbctext, (size_t) i);
  548.  
  549.     (void) (*axif->output) (axif, Ax25multi[IDCALL], axif->hwaddr, PID_NO_L3, hbp);    /* send it */
  550. }
  551.  
  552.  
  553.  
  554. int
  555. doaxheard (int argc, char *argv[], void *p OPTIONAL)
  556. {
  557. struct iface *ifp;
  558.  
  559.     if (argc > 1) {
  560.         if ((ifp = if_lookup (argv[1])) == NULLIF) {
  561.             tprintf (Badinterface, argv[1]);
  562.             return 1;
  563.         }
  564.         if (ifp->output != ax_output) {
  565.             tprintf (alsonotax25, argv[1]);
  566.             return 1;
  567.         }
  568.         if (ifp->flags & LOG_AXHEARD)
  569.             (void) axheard (ifp);
  570.         else
  571.             tputs (notactive);
  572.         return 0;
  573.     }
  574.     for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next) {
  575.         if (ifp->output != ax_output)
  576.             continue;    /* Not an ax.25 interface */
  577.         if (axheard (ifp) == EOF)
  578.             break;
  579.     }
  580.     return 0;
  581. }
  582.  
  583.  
  584.  
  585. int
  586. axheard (struct iface *ifp)
  587. {
  588. int col = 0;
  589. struct lq *lp;
  590. char tmp[AXBUF];
  591.  
  592.     if (ifp->hwaddr == NULLCHAR)
  593.         return 0;
  594.  
  595.     tputs (heardheader);
  596.     tprintf (heardfmt, ifp->name, pax25 (tmp, ifp->hwaddr),
  597.          tformat (secclock () - ifp->lastsent), ifp->rawsndcnt);
  598.  
  599.     tputs (heardheader2);
  600.     for (lp = Lq; lp != NULLLQ; lp = lp->next) {
  601.         if (lp->iface != ifp)
  602.             continue;
  603.         if (col)
  604.             tputs ("  : ");
  605.         if (tprintf ("%-9s   %12s    %7lu", pax25 (tmp, lp->addr), tformat (secclock () - lp->time), lp->currxcnt) == EOF)
  606.             return EOF;
  607.         if (col) {
  608.             if (tputc ('\n') == EOF)
  609.                 return EOF;
  610.             else
  611.                 col = 0;
  612.         } else
  613.             col = 1;
  614.     }
  615.     if (col)
  616.         tputc ('\n');
  617.     return 0;
  618. }
  619.  
  620.  
  621.  
  622. static int
  623. doaxdest (int argc, char *argv[], void *p OPTIONAL)
  624. {
  625. struct iface *ifp;
  626.  
  627.     if (argc > 1) {
  628.         if ((ifp = if_lookup (argv[1])) == NULLIF) {
  629.             tprintf (Badinterface, argv[1]);
  630.             return 1;
  631.         }
  632.         if (ifp->output != ax_output) {
  633.             tprintf (alsonotax25, argv[1]);
  634.             return 1;
  635.         }
  636.         (void) axdest (ifp);
  637.         return 0;
  638.     }
  639.     for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next) {
  640.         if (ifp->output != ax_output)
  641.             continue;    /* Not an ax.25 interface */
  642.         if (axdest (ifp) == EOF)
  643.             break;
  644.     }
  645.     return 0;
  646. }
  647.  
  648.  
  649.  
  650. static int
  651. axdest (struct iface *ifp)
  652. {
  653. struct ld *lp;
  654. struct lq *lq;
  655. char tmp[AXBUF];
  656.  
  657.     if (ifp->hwaddr == NULLCHAR)
  658.         return 0;
  659.     tprintf ("%s:\n", ifp->name);
  660.     tputs (destheader);
  661.     for (lp = Ld; lp != NULLLD; lp = lp->next) {
  662.         if (lp->iface != ifp)
  663.             continue;
  664.  
  665.         tprintf ("%-10s%-17s", pax25 (tmp, lp->addr), tformat (secclock () - lp->time));
  666.  
  667.         if (addreq (lp->addr, ifp->hwaddr)) {
  668.             /* Special case; it's our address */
  669.             tprintf (str17, tformat (secclock () - ifp->lastsent));
  670.         } else if ((lq = al_lookup (ifp, lp->addr, 0)) == NULLLQ)
  671.             tprintf (str17, "");
  672.         else
  673.             tprintf (str17, tformat (secclock () - lq->time));
  674.  
  675.         if (tprintf ("%8lu\n", lp->currxcnt) == EOF)
  676.             return EOF;
  677.     }
  678.     return 0;
  679. }
  680.  
  681.  
  682.  
  683. static int
  684. doaxfilter (int argc, char *argv[], void *p OPTIONAL)
  685. {
  686.     if (argc >= 2)
  687.         (void) setint (&axheard_filter_flag, heardfilter, argc, argv);
  688.     else {
  689.         tputs (filterusage);
  690.         return 1;
  691.     }
  692.  
  693.     tprintf (filtersrc, (axheard_filter_flag & AXHEARD_NOSRC) ? "dis" : "en");
  694.     tprintf (filterdest, (axheard_filter_flag & AXHEARD_NODST) ? "dis" : "en");
  695.     return 0;
  696. }
  697.  
  698.  
  699.  
  700. static int
  701. doaxflush (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  702. {
  703. struct iface *ifp;
  704. #ifndef POOLED
  705. struct lq *lp, *lp1;
  706. struct ld *ld, *ld1;
  707. #endif
  708.  
  709.     for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next) {
  710.         if (ifp->output != ax_output)
  711.             continue;    /* Not an ax.25 interface */
  712.         ifp->rawsndcnt = 0;
  713.     }
  714. #ifdef POOLED
  715.     pool_free (&lq_pool);
  716. #else
  717.     for (lp = Lq; lp != NULLLQ; lp = lp1) {
  718.         lp1 = lp->next;
  719.         free ((char *) lp);
  720.     }
  721. #endif
  722.     Lq = NULLLQ;
  723. #ifdef POOLED
  724.     pool_free (&ld_pool);
  725. #else
  726.     for (ld = Ld; ld != NULLLD; ld = ld1) {
  727.         ld1 = ld->next;
  728.         free ((char *) ld);
  729.     }
  730. #endif
  731.     Ld = NULLLD;
  732.     return 0;
  733. }
  734.  
  735.  
  736.  
  737. static int
  738. doaxreset (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  739. {
  740. struct ax25_cb *axp;
  741.  
  742.     axp = (struct ax25_cb *) htoi (argv[1]);
  743.     if (!ax25val (axp)) {
  744.         tputs (Notval);
  745.         return 1;
  746.     }
  747.     (void) reset_ax25 (axp);
  748.     return 0;
  749. }
  750.  
  751.  
  752.  
  753. /* Display AX.25 link level control blocks */
  754. int
  755. doaxstat (int argc, char *argv[], void *p OPTIONAL)
  756. {
  757. register struct ax25_cb *axp;
  758. char tmp[AXBUF];
  759. char tmp2[AXBUF];
  760.  
  761.     if (argc < 2) {
  762.         tputs (axstatheader);
  763.         for (axp = Ax25_cb; axp != NULLAX25; axp = axp->next) {
  764.             if (tprintf (axstatfmt, axp, len_q (axp->txq), len_p (axp->rxq),
  765.                pax25 (tmp, axp->remote), pax25 (tmp2, axp->local),
  766.                (axp->iface) ? axp->iface->name : "", Ax25states[axp->state]) == EOF)
  767.                 return 0;
  768.         }
  769.         return 0;
  770.     }
  771.     axp = (struct ax25_cb *) htoi (argv[1]);
  772.     if (!ax25val (axp)) {
  773.         tputs (Notval);
  774.         return 1;
  775.     }
  776.     st_ax25 (axp);
  777.     return 0;
  778. }
  779.  
  780.  
  781.  
  782. static void
  783. displaycounters (struct iface *ifp, int addseparator)
  784. {
  785. struct ax25_counters *ac;
  786.  
  787.     ac = &ifp->axcnt;
  788. #if 0
  789.     if (addseparator)
  790.         tprintf ("---------------------------------------------------------------------\n");
  791.     tprintf ("\nAX25 Counters for Interface: %s\n\n", ifp->name);
  792.  
  793.     tprintf ("Total Frames: %10ld in %10ld out\n Data Frames: %10ld in %10ld out\n",
  794.         ac->msgin, ac->msgout, ac->datain, ac->dataout);
  795.     tprintf ("    Segments: %10ld in %10ld out %10ld errors\n        RNRs: %10ld in %10ld out\n",
  796.         ac->segin, ac->segout, ac->segerr, ac->rnrin, ac->rnrout);
  797.     tprintf ("        REJs: %10ld in %10ld out\n     Retries: %10ld\n   FRMR Recv: %10ld\n\n",
  798.         ac->rejin, ac->rejout, ac->retries, ac->frmerr);
  799. #else
  800.     if (!addseparator)
  801.         tprintf ("\nAX25 Counters:\n\n"
  802.             "       <-Frame Count-> <-Data Frames-> <-Segmented-> <--RNR--> <-REJ->     FRMR\n"
  803.             "name        in     out      in     out   in  out err   in  out  in out Rtry  in\n"
  804.             "------ ------- ------- ------- ------- ---- ---- --- ---- ---- --- --- ---- ---\n");
  805.     else if ((addseparator % 5) == 0)
  806.         tprintf ("-------------------------------------------------------------------------------\n");
  807.     
  808.     tprintf ("%-7.7s%7ld %7ld %7ld %7ld %4ld %4ld %3ld %4ld %4ld %3ld %3ld %4ld %3ld\n",
  809.         ifp->name, ac->msgin, ac->msgout, ac->datain, ac->dataout, ac->segin,
  810.         ac->segout, ac->segerr, ac->rnrin, ac->rnrout, ac->rejin, ac->rejout,
  811.         ac->retries, ac->frmerr);
  812. #endif
  813. }
  814.  
  815.  
  816.  
  817. /* Display AX.25 link level counters */
  818. int
  819. doaxcounters (int argc, char *argv[], void *p OPTIONAL)
  820. {
  821. struct iface *ifp;
  822. int count = 0;
  823. int k;
  824.  
  825.     if (argc < 2) {
  826.         for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)    {
  827.             if (ifp->iftype->type == CL_AX25)    {
  828.                 displaycounters (ifp, count);
  829.                 count++;
  830.             }
  831.         }
  832.         return 0;
  833.     }
  834.     for (k = 1; k < argc; k++)    {
  835.         if ((ifp = if_lookup (argv[k])) == NULLIF) {
  836.             tprintf (Badinterface, argv[k]);
  837.             return 1;
  838.         }
  839.         displaycounters (ifp, count);
  840.         count++;
  841.     }
  842.     return 0;
  843. }
  844.  
  845.  
  846.  
  847. /* Dump one control block */
  848. void
  849. st_ax25 (register struct ax25_cb *axp)
  850. {
  851. char tmp[AXBUF];
  852. char tmp2[AXBUF];
  853. int i;
  854. char target[AXALEN];
  855.  
  856.     if (axp == NULLAX25)
  857.         return;
  858.     tputs (axcbheader);
  859.     tprintf (axcbfmt, axp, pax25 (tmp, axp->local),
  860.          pax25 (tmp2, axp->remote), (axp->iface) ? axp->iface->name : "",
  861.          axp->flags.rejsent ? 'R' : ' ', axp->flags.remotebusy ? 'B' : ' ');
  862.     tprintf (" %4d %4d", axp->vs, axp->vr);
  863.     tprintf (" %02u/%02u %u", axp->unack, axp->maxframe, axp->proto);
  864.     tprintf (" %02u/%02u", axp->retries, axp->n2);
  865.     tprintf (" %s\n", Ax25states[axp->state]);
  866.     tprintf (srttmdev, axp->srt, axp->mdev);
  867.     tprintf (T1_4str, '1');
  868.     if (run_timer (&axp->t1))
  869.         tprintf (lustr, read_timer (&axp->t1));
  870.     else
  871.         tputs (stopstr);
  872.     tprintf (lumsstr, dur_timer (&axp->t1));
  873.  
  874.     tprintf (T1_4str, '3');
  875.     if (run_timer (&axp->t3))
  876.         tprintf (lustr, read_timer (&axp->t3));
  877.     else
  878.         tputs (stopstr);
  879.     tprintf (lumsstr, dur_timer (&axp->t3));
  880.  
  881.     tprintf (T1_4str, '4');
  882.     if (run_timer (&axp->t4))
  883.         tprintf (lustr, (read_timer (&axp->t4) / 1000L));
  884.     else
  885.         tputs (stopstr);
  886.     tprintf ("/%lu sec\n", (dur_timer (&axp->t4) / 1000L));
  887.     if (axp->route != NULLAXR)    {
  888.         /* if the route is set, then it is a connection that
  889.            originated from here, and we know definitively this info */
  890.         tputs ("mode = ");
  891.         switch (axp->route->mode) {
  892.             case AX_VC_MODE:    tputs ("VC");
  893.                         break;
  894.             case AX_DATMODE:    tputs ("DG");
  895.                         break;
  896.             case AX_DEFMODE:    tputs ("IF");
  897.                         break;
  898.             default:        tputs ("??");
  899.                         break;
  900.         }
  901.         tputs ("  Digipeaters =");
  902.         for (i = 0; i < axp->route->ndigis; i++) {
  903.             memcpy (target, axp->route->digis[i], AXALEN);
  904.             tprintf (" %s", pax25 (tmp, target));
  905.         }
  906.         tputc ('\n');
  907.     }
  908. }
  909.  
  910.  
  911.  
  912. /* Set limit on retransmission backoff */
  913. int
  914. doax25blimit (int argc, char *argv[], void *p)
  915. {
  916.     return setlong ((long *) p, blimitstr, argc, argv);
  917. }
  918.  
  919.  
  920.  
  921. /* Set limit on retransmission backoff */
  922. static int
  923. doblimit (int argc, char *argv[], void *p OPTIONAL)
  924. {
  925.     return doax25blimit (argc, argv, (void *) &Blimit);
  926. }
  927.  
  928.  
  929.  
  930. /* Set limit on retransmission in ms */
  931. int
  932. doax25maxwait (int argc, char *argv[], void *p)
  933. {
  934.     return setlong ((long *) p, maxwaitstr, argc, argv);
  935. }
  936.  
  937.  
  938.  
  939. static int
  940. doaxmaxwait (int argc, char *argv[], void *p OPTIONAL)
  941. {
  942.     return doax25maxwait (argc, argv, (void *) &Axmaxwait);
  943. }
  944.  
  945.  
  946.  
  947. /* Display or change our AX.25 address */
  948. static int
  949. domycall (int argc, char *argv[], void *p OPTIONAL)
  950. {
  951. char tmp[AXBUF];
  952.  
  953.     if (argc < 2) {
  954.         tprintf (strCR, pax25 (tmp, Mycall));
  955.         return 0;
  956.     }
  957.     if (setcall (Mycall, argv[1]) == -1)
  958.         return -1;
  959. #ifdef MAILBOX
  960.     setmbnrid ();
  961. #endif
  962.     if (!memcmp (AXuser, NOCALL, AXALEN))
  963.         (void) setcall (AXuser, argv[1]);
  964.     return 0;
  965. }
  966.  
  967.  
  968.  
  969. #ifdef TTYCALL
  970. /* Display or change ttylink AX.25 address */
  971. static int
  972. dottycall (int argc, char *argv[], void *p OPTIONAL)
  973. {
  974. char tmp[AXBUF];
  975.  
  976.     if (argc < 2) {
  977.         tprintf (strCR, pax25 (tmp, Ttycall));
  978.         return 0;
  979.     }
  980.     if (setcall (Ttycall, argv[1]) == -1)
  981.         return -1;
  982.     return 0;
  983. }
  984. #endif
  985.  
  986.  
  987.  
  988. static int
  989. doaxuser (int argc, char *argv[], void *p OPTIONAL)
  990. {
  991. char tmp[AXBUF];
  992.  
  993.     if (argc < 2) {
  994.         tprintf (strCR, pax25 (tmp, AXuser));
  995.         return 0;
  996.     }
  997.     if (setcall (AXuser, argv[1]) == -1)
  998.         return -1;
  999.     return 0;
  1000. }
  1001.  
  1002.  
  1003.  
  1004. /* Control AX.25 digipeating */
  1005. static int
  1006. dodigipeat (int argc, char *argv[], void *p)
  1007. {
  1008.     return (dosetflag (argc, argv, p, AX25_DIGI, 1));
  1009. }
  1010.  
  1011.  
  1012.  
  1013. int
  1014. doax25version (int argc, char *argv[], void *p)
  1015. {
  1016.     return setshort ((unsigned short *) p, axversionstr, argc, argv);
  1017. }
  1018.  
  1019.  
  1020.  
  1021. static int
  1022. doaxversion (int argc, char *argv[], void *p OPTIONAL)
  1023. {
  1024.     return doax25version (argc, argv, (void *) &Axversion);
  1025. }
  1026.  
  1027.  
  1028.  
  1029. static int
  1030. doax25irtt (int argc, char *argv[], void *p)
  1031. {
  1032.     return setlong ((long *) p, irttstr, argc, argv);
  1033. }
  1034.  
  1035.  
  1036.  
  1037. static int
  1038. doaxirtt (int argc, char *argv[], void *p OPTIONAL)
  1039. {
  1040.     return doax25irtt (argc, argv, (void *) &Axirtt);
  1041. }
  1042.  
  1043.  
  1044.  
  1045. /* Set idle timer */
  1046. int
  1047. doax25t3 (int argc, char *argv[], void *p)
  1048. {
  1049.     return setlong ((long *) p, polltimerstr, argc, argv);
  1050. }
  1051.  
  1052.  
  1053.  
  1054. /* Set idle timer */
  1055. static int
  1056. dot3 (int argc, char *argv[], void *p OPTIONAL)
  1057. {
  1058.     return doax25t3 (argc, argv, &T3init);
  1059. }
  1060.  
  1061.  
  1062.  
  1063. /* Set link redundancy timer */
  1064. int
  1065. doax25t4 (int argc, char *argv[], void *p)
  1066. {
  1067.     return setlong ((long *) p, redundancystr, argc, argv);
  1068. }
  1069.  
  1070.  
  1071.  
  1072. /* Set link redundancy timer */
  1073. static int
  1074. dot4 (int argc, char *argv[], void *p OPTIONAL)
  1075. {
  1076.     return doax25t4 (argc, argv, (long *) &T4init);
  1077. }
  1078.  
  1079.  
  1080.  
  1081. /* Set retry limit count */
  1082. int
  1083. doax25n2 (int argc, char *argv[], void *p)
  1084. {
  1085.     return setshort ((unsigned short *) p, retrylimitstr, argc, argv);
  1086. }
  1087.  
  1088.  
  1089.  
  1090. /* Set retry limit count */
  1091. static int
  1092. don2 (int argc, char *argv[], void *p OPTIONAL)
  1093. {
  1094.     return doax25n2 (argc, argv, (void *) &N2);
  1095. }
  1096.  
  1097.  
  1098.  
  1099. /* Force a retransmission */
  1100. static int
  1101. doaxkick (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  1102. {
  1103. struct ax25_cb *axp;
  1104.  
  1105.     axp = (struct ax25_cb *) htoi (argv[1]);
  1106.     if (!ax25val (axp)) {
  1107.         tputs (Notval);
  1108.         return 1;
  1109.     }
  1110.     (void) kick_ax25 (axp);
  1111.     return 0;
  1112. }
  1113.  
  1114.  
  1115.  
  1116. /* Set maximum number of frames that will be allowed in flight */
  1117. int
  1118. doax25maxframe (int argc, char *argv[], void *p)
  1119. {
  1120.     return setshort ((unsigned short *) p, maxframestr, argc, argv);
  1121. }
  1122.  
  1123.  
  1124.  
  1125. /* Set maximum number of frames that will be allowed in flight */
  1126. static int
  1127. domaxframe (int argc, char *argv[], void *p OPTIONAL)
  1128. {
  1129.     return doax25maxframe (argc, argv, (void *) &Maxframe);
  1130. }
  1131.  
  1132.  
  1133.  
  1134. /* Set maximum length of I-frame data field */
  1135. int
  1136. doax25paclen (int argc, char *argv[], void *p)
  1137. {
  1138.     return setshort ((unsigned short *) p, paclenstr, argc, argv);
  1139. }
  1140.  
  1141.  
  1142.  
  1143. /* Set maximum length of I-frame data field */
  1144. static int
  1145. dopaclen (int argc, char *argv[], void *p OPTIONAL)
  1146. {
  1147.     return doax25paclen (argc, argv, (void *) &Paclen);
  1148. }
  1149.  
  1150.  
  1151.  
  1152. /* Set size of I-frame above which polls will be sent after a timeout */
  1153. int
  1154. doax25pthresh (int argc, char *argv[], void *p)
  1155. {
  1156.     return setshort ((unsigned short *) p, pthreshstr, argc, argv);
  1157. }
  1158.  
  1159.  
  1160.  
  1161. /* Set size of I-frame above which polls will be sent after a timeout */
  1162. static int
  1163. dopthresh (int argc, char *argv[], void *p OPTIONAL)
  1164. {
  1165.     return doax25pthresh (argc, argv, (void *) &Pthresh);
  1166. }
  1167.  
  1168.  
  1169.  
  1170. /* Set high water mark on receive queue that triggers RNR */
  1171. int
  1172. doax25window (int argc, char *argv[], void *p)
  1173. {
  1174.     return setshort ((unsigned short *) p, windowstr, argc, argv);
  1175. }
  1176.  
  1177.  
  1178.  
  1179. /* Set high water mark on receive queue that triggers RNR */
  1180. static int
  1181. doaxwindow (int argc, char *argv[], void *p OPTIONAL)
  1182. {
  1183.     return doax25window (argc, argv, (void *) &Axwindow);
  1184. }
  1185.  
  1186.  
  1187.  
  1188. /* End of ax25 subcommands */
  1189.  
  1190. #if defined(AX25) || defined(MAILBOX) || defined(AXUI)
  1191. /* Consolidate into one place the parsing of a connect path containing digipeaters.
  1192.  * This is for gateway connects, by console connect cmd, by the
  1193.  * axui command, and by the BBS forwarding process.
  1194.  * We will place the derived path into the ax25 route table.
  1195.  * Input: tokenized cmd line argc/argv: cmd iface target [via] digi1 [,] digi2 ... digiN
  1196.  *        interface *ifp.
  1197.  *        target, the node reached via digipeating.
  1198.  * Output: ax25 route table is updated.
  1199.  * Return code: 0 => error, else number of digis in path.  -- K5JB
  1200. */
  1201. int
  1202. connect_filt (int argc, char *argv[], char target[], struct iface *ifp, int mode)
  1203. {
  1204. int i, rtn_argc, ndigis, dreg_flag = 0;
  1205. char digis[MAXDIGIS][AXALEN];
  1206. char *nargv[MAXDIGIS + 1];
  1207. char *cp, *dreg = NULLCHAR;
  1208.  
  1209.     ndigis = argc - 3;    /* worst case */
  1210.  
  1211.     for (i = 0, rtn_argc = 0; i < ndigis && rtn_argc < MAXDIGIS + 1; i++) {
  1212.         cp = argv[i + 3];
  1213.  
  1214. get_dreg:
  1215.         switch (*cp) {
  1216.             case ',':
  1217.                 if (!*(cp + 1))    /* lone comma */
  1218.                     continue;    /* skip it */
  1219.                 else {    /* leading comma, a faux pas */
  1220.                     nargv[rtn_argc++] = ++cp;
  1221.                     if (*cp == ',') {    /* sequential commas are illegal */
  1222.                         rtn_argc = MAXDIGIS + 1;    /* force for() loop exit */
  1223.                         continue;
  1224.                     }
  1225.                     break;
  1226.                 }
  1227.             case 'v':
  1228.                 if (!strncmp ("via", cp, strlen (cp)))    /* should get 'em all */
  1229.                     continue;    /* skip it */
  1230.             default:
  1231.                 nargv[rtn_argc++] = cp;
  1232.                 break;
  1233.         }
  1234.         for (; *cp; cp++)    /* remove any trailing commas */
  1235.             if (*cp == ',') {
  1236.                 *cp = '\0';
  1237.                 if (*(cp + 1) != '\0') {    /* something dangling */
  1238.                     dreg = cp + 1;    /* restart scan here */
  1239.                     dreg_flag = 1;
  1240.                 }
  1241.                 break;
  1242.             }
  1243.         if (dreg_flag) {
  1244.             dreg_flag = 0;
  1245.             cp = dreg;    /* go back and get the dreg */
  1246.             goto get_dreg;
  1247.         }
  1248.     }
  1249.  
  1250.     if (rtn_argc > MAXDIGIS || ndigis < 1) {
  1251.         tputs (toomany);
  1252.         return 0;
  1253.     }
  1254.     for (i = 0; i < rtn_argc; i++) {
  1255.         if (setcall (digis[i], nargv[i]) == -1) {    /*lint !e771 */
  1256.             tprintf (baddigi, nargv[i]);
  1257.             return 0;
  1258.         }
  1259.     }
  1260.     if (ax_add (target, mode, digis, rtn_argc, ifp) == NULLAXR) {
  1261.         tputs (addfailed);
  1262.         return 0;
  1263.     }
  1264.     return (rtn_argc);
  1265. }
  1266.  
  1267. #endif
  1268.  
  1269.  
  1270.  
  1271. /* Initiate interactive AX.25 connect to remote station */
  1272. int
  1273. doconnect (int argc, char *argv[], void *p OPTIONAL)
  1274. {
  1275. struct sockaddr_ax fsocket;
  1276. struct session *sp;
  1277. struct iface *ifp;
  1278. char target[AXALEN];
  1279. int split = 0;
  1280. char tmp[AXBUF];
  1281.  
  1282.     /*Make sure this comes from console - WG7J*/
  1283.     if (Curproc->input != Command->input)
  1284.         return 0;
  1285.  
  1286. #ifdef ALLSERV
  1287.     if (argv[0][0] == 's')    /* use split screen */
  1288.         split = 1;
  1289. #endif
  1290.  
  1291.     if (((ifp = if_lookup (argv[1])) != NULLIF) && (ifp->type != CL_AX25)) {
  1292.         tprintf (alsonotax25, argv[1]);
  1293.         return 1;
  1294.     }
  1295.     if (ifp == NULLIF) {
  1296.         tprintf (Badinterface, argv[1]);
  1297. #if defined(MAILBOX) && defined(GATECMDS)
  1298.         (void) dombports (0, NULL, NULL);
  1299. #endif
  1300.         return 1;
  1301.     }
  1302.     if (argc > 3 && !strcmp (argv[3], "@")) {
  1303.         free (argv[3]);
  1304.         argv[3] = strdup (pax25 (tmp, AXRosecall));
  1305.     }
  1306.     if (setcall (target, argv[2]) == -1) {
  1307.         tprintf (badcallsign, argv[2]);
  1308.         return 1;
  1309.     }
  1310.     /* If digipeaters are given, put them in the routing table */
  1311.     if (argc > 3) {
  1312.         if (connect_filt (argc, argv, target, ifp, AX_SETUP) == 0)
  1313.             return 1;
  1314.     }
  1315.     /* Allocate a session descriptor */
  1316.     if ((sp = newsession (argv[2], AX25TNC, split)) == NULLSESSION) {
  1317.         tputs (TooManySessions);
  1318.         return 1;
  1319.     }
  1320.     if ((sp->s = socket (AF_AX25, SOCK_STREAM, 0)) == -1) {
  1321.         tputs (Nosock);
  1322.         freesession (sp);
  1323.         (void) keywait (NULLCHAR, 1);
  1324.         return 1;
  1325.     }
  1326.     fsocket.sax_family = AF_AX25;
  1327.  
  1328.     memcpy (fsocket.ax25_addr, AXuser, AXALEN);
  1329.     (void) bind (sp->s, (char *) &fsocket, sizeof (struct sockaddr_ax));
  1330.  
  1331.     (void) setcall (fsocket.ax25_addr, argv[2]);
  1332.     strncpy (fsocket.iface, argv[1], ILEN - 1);
  1333.     return tel_connect (sp, (char *) &fsocket, sizeof (struct sockaddr_ax));
  1334. }
  1335.  
  1336.  
  1337.  
  1338. /* Display and modify AX.25 routing table */
  1339. static int
  1340. doaxroute (int argc, char *argv[], void *p OPTIONAL)
  1341. {
  1342. char tmp[AXBUF];
  1343. int i, ndigis;
  1344. register struct ax_route *axr;
  1345. struct ax_route **routetbl = &Ax_setups;
  1346. char target[AXALEN], digis[MAXDIGIS][AXALEN];
  1347. struct iface *iface;
  1348. const char *typestr;
  1349.  
  1350.     if (argc < 2) {
  1351.         tputs (routeheader);
  1352.         do    {
  1353.             for (axr = *routetbl; axr != NULLAXR; axr = axr->next) {
  1354.                 memcpy (target, axr->target, AXALEN);
  1355.                 target[AXALEN - 1] |= (AXN | Q);
  1356.                 switch (axr->type)    {
  1357.                     case AX_LOCAL:        typestr = "Local";
  1358.                                 break;
  1359.                     case AX_SETUP:        typestr = "Setup";
  1360.                                 break;
  1361.                     default:        typestr = "Auto";
  1362.                 }
  1363.                 tprintf ("%-10s%-7s%-6s", pax25 (tmp, target),
  1364.                      axr->iface->name, typestr);
  1365.                 switch (axr->mode) {
  1366.                     case AX_VC_MODE:    tputs (" VC ");
  1367.                                 break;
  1368.                     case AX_DATMODE:    tputs (" DG ");
  1369.                                 break;
  1370.                     case AX_DEFMODE:    tputs (" IF ");
  1371.                                 break;
  1372.                     default:        tputs (" ?? ");
  1373.                                 break;
  1374.                 }
  1375.  
  1376.                 for (i = 0; i < axr->ndigis; i++) {
  1377.                     memcpy (target, axr->digis[i], AXALEN);
  1378. #if 0                    /* shouldn't be needed */
  1379.                     target[AXALEN - 1] |= (AXN | Q);
  1380. #endif
  1381.                     tprintf (" %s", pax25 (tmp, target));
  1382.                 }
  1383.                 if (tputc ('\n') == EOF)
  1384.                     return 0;
  1385.             }
  1386.             if (routetbl == &Ax_setups)
  1387.                 routetbl = &Ax_routes;
  1388.             else
  1389.                 routetbl = (struct ax_route **)0;
  1390.         } while (routetbl != (struct ax_route **)0);
  1391.         return 0;
  1392.     }
  1393.     if (argc < 4) {
  1394.         tputs (routeusage);
  1395.         return 1;
  1396.     }
  1397.     if (setcall (target, argv[2]) == -1) {
  1398.         tprintf (badtarget, argv[2]);
  1399.         return 1;
  1400.     }
  1401.     if ((iface = if_lookup (argv[3])) == NULLIF) {
  1402.         tprintf (Badinterface, argv[3]);
  1403.         return 1;
  1404.     }
  1405.     switch (argv[1][0]) {
  1406.         case 'a':    /* Add route */
  1407.             ndigis = argc - 4;
  1408.             if (ndigis > MAXDIGIS) {
  1409.                 tputs (toomany);
  1410.                 return 1;
  1411.             }
  1412.             for (i = 0; i < ndigis; i++) {
  1413.                 if (setcall (digis[i], argv[i + 4]) == -1) {
  1414.                     tprintf (baddigi, argv[i + 4]);
  1415.                     return 1;
  1416.                 }
  1417.             }
  1418.             if (ax_add (target, AX_LOCAL, digis, ndigis, iface) == NULLAXR) {
  1419.                 tputs (addfailed);
  1420.                 return 1;
  1421.             }
  1422.             break;
  1423.         case 'd':    /* Drop route */
  1424.             if (ax_drop (target, iface, AX_NONSETUP) == -1) {
  1425.                 tputs (notintable);
  1426.                 return 1;
  1427.             }
  1428.             break;
  1429.         case 'm':    /* Alter route mode */
  1430.             if (argc < 5) {
  1431.                 tputs (routeusage);
  1432.                 return 1;
  1433.             }
  1434.             if ((axr = ax_lookup (NULLCHAR, target, iface, AX_NONSETUP)) == NULLAXR) {
  1435.                 tputs (notintable);
  1436.                 return 1;
  1437.             }
  1438.             switch (argv[4][0]) {
  1439.                 case 'i':    /* use default interface mode */
  1440.                     axr->mode = AX_DEFMODE;
  1441.                     break;
  1442.                 case 'v':    /* use virtual circuit mode */
  1443.                     axr->mode = AX_VC_MODE;
  1444.                     break;
  1445.                 case 'd':    /* use datagram mode */
  1446.                     axr->mode = AX_DATMODE;
  1447.                     break;
  1448.                 default:
  1449.                     tprintf (unknownmode, argv[4]);
  1450.                     return 1;
  1451.             }
  1452.             break;
  1453.         default:
  1454.             tprintf (unknowncmd, argv[1]);
  1455.             return 1;
  1456.     }
  1457.     return 0;
  1458. }
  1459.  
  1460.  
  1461.  
  1462. /* ax25 timers type - linear v exponential */
  1463. int
  1464. doax25timertype (int argc, char *argv[], void *p)
  1465. {
  1466.  
  1467.     if (argc < 2) {
  1468.         tputs (timertypestr);
  1469.         switch (*(int *) p) {
  1470.             case 2:
  1471.                 tputs (originalstr);
  1472.                 break;
  1473.             case 1:
  1474.                 tputs (linearstr);
  1475.                 break;
  1476.             case 0:
  1477.                 tputs (exponentialstr);
  1478.                 break;
  1479.             default:
  1480.                 break;
  1481.         }
  1482.         return 0;
  1483.     }
  1484.     switch (argv[1][0]) {
  1485.         case 'o':
  1486.         case 'O':    *(int *) p = 2;
  1487.                 break;
  1488.         case 'l':
  1489.         case 'L':    *(int *) p = 1;
  1490.                 break;
  1491.         case 'e':
  1492.         case 'E':    *(int *) p = 0;
  1493.                 break;
  1494.         default:    tputs (timertypeusage);
  1495.                 return -1;
  1496.     }
  1497.  
  1498.     return 0;
  1499. }
  1500.  
  1501.  
  1502.  
  1503. /* ax25 timers type - linear v exponential */
  1504. static int
  1505. doaxtype (int argc, char *argv[], void *p OPTIONAL)
  1506. {
  1507.     return doax25timertype (argc, argv, (void *) &lapbtimertype);
  1508. }
  1509.  
  1510.  
  1511.  
  1512. /* Display or change an AX.25 tutorial-type call */
  1513. static int
  1514. docall (int argc, char *argv[], void *p OPTIONAL, char call[])
  1515. {
  1516. char tmp[AXBUF];
  1517.  
  1518.     if (argc < 2) {
  1519.         tprintf (strCR, pax25 (tmp, call));
  1520.         return 0;
  1521.     }
  1522.     if (setcall (call, argv[1]) == -1)
  1523.         return -1;
  1524.     return 0;
  1525. }
  1526.  
  1527.  
  1528.  
  1529. /* Display or change our AX.25 rose entry call */
  1530. static int
  1531. dorosecall (int argc, char *argv[], void *p)
  1532. {
  1533.     return (docall (argc, argv, p, AXRosecall));
  1534. }
  1535.  
  1536.  
  1537.  
  1538. #ifdef TUTOR
  1539. /* Display or change our AX.25 tutorial call */
  1540. static int
  1541. dotutorcall (int argc, char *argv[], void *p)
  1542. {
  1543.     return (docall (argc, argv, p, Tcall));
  1544. }
  1545.  
  1546.  
  1547.  
  1548. /* Display or change our AX.25 info call */
  1549. static int
  1550. doinfocall (int argc, char *argv[], void *p)
  1551. {
  1552.     return (docall (argc, argv, p, Icall));
  1553. }
  1554.  
  1555.  
  1556.  
  1557. /* Display or change our AX.25 news call */
  1558. static int
  1559. donewscall (int argc, char *argv[], void *p)
  1560. {
  1561.     return (docall (argc, argv, p, Ncall));
  1562. }
  1563. #endif
  1564.  
  1565.  
  1566.  
  1567. void 
  1568. init_ifax25 (struct ifax25 *ax25)
  1569. {
  1570.     if (!ax25)
  1571.         return;
  1572.     /* Set interface to the defaults */
  1573.     ax25->paclen = Paclen;
  1574.     ax25->lapbtimertype = lapbtimertype;
  1575.     ax25->irtt = Axirtt;
  1576.     ax25->version = Axversion;
  1577.     ax25->t3 = T3init;
  1578.     ax25->t4 = T4init;
  1579.     ax25->n2 = N2;
  1580.     ax25->maxframe = Maxframe;
  1581.     ax25->pthresh = Pthresh;
  1582.     ax25->window = Axwindow;
  1583.     ax25->blimit = Blimit;
  1584.     ax25->maxwait = Axmaxwait;
  1585.     if (axbctext)
  1586.         ax25->bctext = strdup (axbctext);
  1587. }
  1588.  
  1589.  
  1590. static int doifax25paclen (int argc, char *argv[], void *p);
  1591. static int doifax25timertype (int argc, char *argv[], void *p);
  1592. static int doifax25irtt (int argc, char *argv[], void *p);
  1593. static int doifax25version (int argc, char *argv[], void *p);
  1594. static int doifax25t3 (int argc, char *argv[], void *p);
  1595. static int doifax25t4 (int argc, char *argv[], void *p);
  1596. static int doifax25n2 (int argc, char *argv[], void *p);
  1597. static int doifax25maxframe (int argc, char *argv[], void *p);
  1598. static int doifax25pthresh (int argc, char *argv[], void *p);
  1599. static int doifax25window (int argc, char *argv[], void *p);
  1600. static int doifax25blimit (int argc, char *argv[], void *p);
  1601. static int doifax25maxwait (int argc, char *argv[], void *p);
  1602. static int doifax25bctext (int argc, char *argv[], void *p);
  1603.  
  1604.  
  1605.  
  1606. /* These are the command that set ax.25 parameters per interface */
  1607. static struct cmds Ifaxcmds[] =
  1608. {
  1609.     { "bctext",    doifax25bctext,        0, 0, NULLCHAR },
  1610.     { "blimit",    doifax25blimit,        0, 0, NULLCHAR },
  1611.     { "irtt",    doifax25irtt,        0, 0, NULLCHAR },
  1612.     { "maxframe",    doifax25maxframe,    0, 0, NULLCHAR },
  1613.     { "maxwait",    doifax25maxwait,    0, 0, NULLCHAR },
  1614.     { "paclen",    doifax25paclen,        0, 0, NULLCHAR },
  1615.     { "pthresh",    doifax25pthresh,    0, 0, NULLCHAR },
  1616.     { "retries",    doifax25n2,        0, 0, NULLCHAR },
  1617.     { "timertype",    doifax25timertype,    0, 0, NULLCHAR },
  1618.     { "t3",        doifax25t3,        0, 0, NULLCHAR },
  1619.     { "t4",        doifax25t4,        0, 0, NULLCHAR },
  1620.     { "version",    doifax25version,    0, 0, NULLCHAR },
  1621.     { "window",    doifax25window,        0, 0, NULLCHAR },
  1622.     { NULLCHAR,    NULL,            0, 0, NULLCHAR }
  1623. };
  1624.  
  1625.  
  1626.  
  1627. int 
  1628. ifax25 (int argc, char *argv[], void *p)
  1629. {
  1630.  
  1631.     if (((struct iface *) p)->type != CL_AX25)
  1632.         return tputs (notax25);
  1633.     return subcmd (Ifaxcmds, argc, argv, p);
  1634. }
  1635.  
  1636.  
  1637.  
  1638. /* Set ax.25 bctext */
  1639. static int
  1640. doifax25bctext (int argc, char *argv[], void *p)
  1641. {
  1642. struct iface *ifp = p;
  1643.  
  1644.     if (argc == 1)
  1645.         tprintf (bctext_str, ifp->ax25->bctext);
  1646.     else {
  1647.         if (ifp->ax25->bctext)
  1648.             free (ifp->ax25->bctext);
  1649.         if (strlen (argv[1]) == 0)    /* clearing the buffer */
  1650.             ifp->ax25->bctext = NULL;
  1651.         else
  1652.             ifp->ax25->bctext = strdup (argv[1]);
  1653.     }
  1654.     return 0;
  1655. }
  1656.  
  1657.  
  1658.  
  1659. static int
  1660. doifax25blimit (int argc, char *argv[], void *p)
  1661. {
  1662. struct iface *ifp = p;
  1663.  
  1664.     return doax25blimit (argc, argv, (void *) &ifp->ax25->blimit);
  1665. }
  1666.  
  1667.  
  1668.  
  1669. static int
  1670. doifax25irtt (int argc, char *argv[], void *p)
  1671. {
  1672. struct iface *ifp = p;
  1673.  
  1674.     return doax25irtt (argc, argv, (void *) &ifp->ax25->irtt);
  1675. }
  1676.  
  1677.  
  1678.  
  1679. static int
  1680. doifax25maxframe (int argc, char *argv[], void *p)
  1681. {
  1682. struct iface *ifp = p;
  1683.  
  1684.     return doax25maxframe (argc, argv, (void *) &ifp->ax25->maxframe);
  1685. }
  1686.  
  1687.  
  1688.  
  1689. static int
  1690. doifax25maxwait (int argc, char *argv[], void *p)
  1691. {
  1692. struct iface *ifp = p;
  1693.  
  1694.     return doax25maxwait (argc, argv, (void *) &ifp->ax25->maxwait);
  1695. }
  1696.  
  1697.  
  1698.  
  1699. /* Set interface AX.25 Paclen, and adjust the NETROM mtu for the
  1700.  * smallest paclen. - WG7J
  1701.  */
  1702. static int
  1703. doifax25paclen (int argc, char *argv[], void *p)
  1704. {
  1705. struct iface *ifp = p;
  1706. #ifdef NETROM
  1707. int tmp;
  1708. #endif
  1709.  
  1710.     (void) doax25paclen (argc, argv, (void *) &ifp->ax25->paclen);
  1711. #ifdef NETROM
  1712.     if (argc > 1 && ifp->flags & IS_NR_IFACE) {
  1713.         if ((tmp = ifp->ax25->paclen - 20) < Nr_iface->mtu)
  1714.             Nr_iface->mtu = (int16) tmp;
  1715.     }
  1716. #endif
  1717.     return 0;
  1718. }
  1719.  
  1720.  
  1721.  
  1722. static int
  1723. doifax25pthresh (int argc, char *argv[], void *p)
  1724. {
  1725. struct iface *ifp = p;
  1726.  
  1727.     return doax25pthresh (argc, argv, (void *) &ifp->ax25->pthresh);
  1728. }
  1729.  
  1730.  
  1731.  
  1732. static int
  1733. doifax25n2 (int argc, char *argv[], void *p)
  1734. {
  1735. struct iface *ifp = p;
  1736.  
  1737.     return doax25n2 (argc, argv, (void *) &ifp->ax25->n2);
  1738. }
  1739.  
  1740.  
  1741.  
  1742. static int
  1743. doifax25timertype (int argc, char *argv[], void *p)
  1744. {
  1745. struct iface *ifp = p;
  1746.  
  1747.     return doax25timertype (argc, argv, (void *) &ifp->ax25->lapbtimertype);
  1748. }
  1749.  
  1750.  
  1751.  
  1752. static int
  1753. doifax25t3 (int argc, char *argv[], void *p)
  1754. {
  1755. struct iface *ifp = p;
  1756.  
  1757.     return doax25t3 (argc, argv, (void *) &ifp->ax25->t3);
  1758. }
  1759.  
  1760.  
  1761.  
  1762. static int
  1763. doifax25t4 (int argc, char *argv[], void *p)
  1764. {
  1765. struct iface *ifp = p;
  1766.  
  1767.     return doax25t4 (argc, argv, (void *) &ifp->ax25->t4);
  1768. }
  1769.  
  1770.  
  1771.  
  1772. static int
  1773. doifax25version (int argc, char *argv[], void *p)
  1774. {
  1775. struct iface *ifp = p;
  1776.  
  1777.     return doax25version (argc, argv, (void *) &ifp->ax25->version);
  1778. }
  1779.  
  1780.  
  1781.  
  1782. static int
  1783. doifax25window (int argc, char *argv[], void *p)
  1784. {
  1785. struct iface *ifp = p;
  1786.  
  1787.     return doax25window (argc, argv, (void *) &ifp->ax25->window);
  1788. }
  1789.  
  1790. #endif /* AX25 */
  1791.